﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using Terraria.ModLoader.Default;
using Terraria.ModLoader.Exceptions;
using Terraria.Social;
using Terraria.Utilities;

namespace Terraria.ModLoader.IO
{
	// Token: 0x020002ED RID: 749
	internal static class PlayerIO
	{
		// Token: 0x06001CF4 RID: 7412 RVA: 0x004374D8 File Offset: 0x004356D8
		internal static void Save(Player player, string path, bool isCloudSave)
		{
			path = Path.ChangeExtension(path, ".tplr");
			if (FileUtilities.Exists(path, isCloudSave))
			{
				FileUtilities.Copy(path, path + ".bak", isCloudSave, true);
			}
			TagCompound tagCompound = new TagCompound();
			tagCompound["armor"] = PlayerIO.SaveInventory(player.armor);
			tagCompound["dye"] = PlayerIO.SaveInventory(player.dye);
			tagCompound["inventory"] = PlayerIO.SaveInventory(player.inventory);
			tagCompound["miscEquips"] = PlayerIO.SaveInventory(player.miscEquips);
			tagCompound["miscDyes"] = PlayerIO.SaveInventory(player.miscDyes);
			tagCompound["bank"] = PlayerIO.SaveInventory(player.bank.item);
			tagCompound["bank2"] = PlayerIO.SaveInventory(player.bank2.item);
			tagCompound["bank3"] = PlayerIO.SaveInventory(player.bank3.item);
			tagCompound["modData"] = PlayerIO.SaveModData(player);
			tagCompound["modBuffs"] = PlayerIO.SaveModBuffs(player);
			tagCompound["usedMods"] = PlayerIO.SaveUsedMods(player);
			TagCompound root = tagCompound;
			using (Stream stream = isCloudSave ? new MemoryStream() : new FileStream(path, FileMode.Create))
			{
				TagIO.ToStream(root, stream, true);
				if (isCloudSave && SocialAPI.Cloud != null)
				{
					SocialAPI.Cloud.Write(path, ((MemoryStream)stream).ToArray());
				}
			}
		}

		// Token: 0x06001CF5 RID: 7413 RVA: 0x00437660 File Offset: 0x00435860
		internal static void Load(Player player, string path, bool isCloudSave)
		{
			path = Path.ChangeExtension(path, ".tplr");
			if (!FileUtilities.Exists(path, isCloudSave))
			{
				return;
			}
			byte[] array = FileUtilities.ReadAllBytes(path, isCloudSave);
			if (array[0] != 31 || array[1] != 139)
			{
				PlayerIO.LoadLegacy(player, array);
				return;
			}
			TagCompound tagCompound = TagIO.FromStream(new MemoryStream(array), true);
			PlayerIO.LoadInventory(player.armor, tagCompound.GetList<TagCompound>("armor"));
			PlayerIO.LoadInventory(player.dye, tagCompound.GetList<TagCompound>("dye"));
			PlayerIO.LoadInventory(player.inventory, tagCompound.GetList<TagCompound>("inventory"));
			PlayerIO.LoadInventory(player.miscEquips, tagCompound.GetList<TagCompound>("miscEquips"));
			PlayerIO.LoadInventory(player.miscDyes, tagCompound.GetList<TagCompound>("miscDyes"));
			PlayerIO.LoadInventory(player.bank.item, tagCompound.GetList<TagCompound>("bank"));
			PlayerIO.LoadInventory(player.bank2.item, tagCompound.GetList<TagCompound>("bank2"));
			PlayerIO.LoadInventory(player.bank3.item, tagCompound.GetList<TagCompound>("bank3"));
			PlayerIO.LoadModData(player, tagCompound.GetList<TagCompound>("modData"));
			PlayerIO.LoadModBuffs(player, tagCompound.GetList<TagCompound>("modBuffs"));
			PlayerIO.LoadUsedMods(player, tagCompound.GetList<string>("usedMods"));
		}

		// Token: 0x06001CF6 RID: 7414 RVA: 0x004377A4 File Offset: 0x004359A4
		public static List<TagCompound> SaveInventory(Item[] inv)
		{
			List<TagCompound> list = new List<TagCompound>();
			for (int i = 0; i < inv.Length; i++)
			{
				if (ItemLoader.NeedsModSaving(inv[i]))
				{
					TagCompound tagCompound = ItemIO.Save(inv[i]);
					tagCompound.Set("slot", (short)i);
					list.Add(tagCompound);
				}
			}
			if (list.Count <= 0)
			{
				return null;
			}
			return list;
		}

		// Token: 0x06001CF7 RID: 7415 RVA: 0x00437800 File Offset: 0x00435A00
		public static void LoadInventory(Item[] inv, IList<TagCompound> list)
		{
			foreach (TagCompound tagCompound in list)
			{
				inv[(int)tagCompound.GetShort("slot")] = ItemIO.Load(tagCompound);
			}
		}

		// Token: 0x06001CF8 RID: 7416 RVA: 0x00437854 File Offset: 0x00435A54
		internal static List<TagCompound> SaveModData(Player player)
		{
			List<TagCompound> list = new List<TagCompound>();
			foreach (ModPlayer modPlayer in player.modPlayers)
			{
				TagCompound tagCompound = modPlayer.Save();
				if (tagCompound != null)
				{
					List<TagCompound> list2 = list;
					TagCompound tagCompound2 = new TagCompound();
					tagCompound2["mod"] = modPlayer.mod.Name;
					tagCompound2["name"] = modPlayer.Name;
					tagCompound2["data"] = tagCompound;
					list2.Add(tagCompound2);
				}
			}
			return list;
		}

		// Token: 0x06001CF9 RID: 7417 RVA: 0x004378CC File Offset: 0x00435ACC
		internal static void LoadModData(Player player, IList<TagCompound> list)
		{
			foreach (TagCompound tagCompound in list)
			{
				Mod mod = ModLoader.GetMod(tagCompound.GetString("mod"));
				ModPlayer modPlayer = (mod == null) ? null : player.GetModPlayer(mod, tagCompound.GetString("name"));
				if (modPlayer != null)
				{
					try
					{
						if (tagCompound.ContainsKey("legacyData"))
						{
							modPlayer.LoadLegacy(new BinaryReader(new MemoryStream(tagCompound.GetByteArray("legacyData"))));
						}
						else
						{
							modPlayer.Load(tagCompound.GetCompound("data"));
						}
						continue;
					}
					catch (Exception inner)
					{
						throw new CustomModDataException(mod, "Error in reading custom player data for " + mod.Name, inner);
					}
				}
				player.GetModPlayer<MysteryPlayer>(ModLoader.GetMod("ModLoader")).data.Add(tagCompound);
			}
		}

		// Token: 0x06001CFA RID: 7418 RVA: 0x004379C0 File Offset: 0x00435BC0
		internal static List<TagCompound> SaveModBuffs(Player player)
		{
			List<TagCompound> list = new List<TagCompound>();
			byte b = 0;
			for (int i = 0; i < 22; i++)
			{
				int num = player.buffType[i];
				if (num != 0 && !Main.buffNoSave[num])
				{
					if (BuffLoader.IsModBuff(num))
					{
						ModBuff buff = BuffLoader.GetBuff(num);
						List<TagCompound> list2 = list;
						TagCompound tagCompound = new TagCompound();
						tagCompound["index"] = b;
						tagCompound["mod"] = buff.mod.Name;
						tagCompound["name"] = buff.Name;
						tagCompound["time"] = player.buffTime[i];
						list2.Add(tagCompound);
					}
					else
					{
						b += 1;
					}
				}
			}
			return list;
		}

		// Token: 0x06001CFB RID: 7419 RVA: 0x00437A74 File Offset: 0x00435C74
		internal static void LoadModBuffs(Player player, IList<TagCompound> list)
		{
			int num = 22;
			while (num > 0 && player.buffType[num - 1] == 0)
			{
				num--;
			}
			foreach (TagCompound tagCompound in list.Reverse<TagCompound>())
			{
				Mod mod = ModLoader.GetMod(tagCompound.GetString("mod"));
				int num2 = (mod != null) ? mod.BuffType(tagCompound.GetString("name")) : 0;
				if (num2 != 0)
				{
					int num3 = Math.Min((int)tagCompound.GetByte("index"), num);
					Array.Copy(player.buffType, num3, player.buffType, num3 + 1, 22 - num3 - 1);
					Array.Copy(player.buffTime, num3, player.buffTime, num3 + 1, 22 - num3 - 1);
					player.buffType[num3] = num2;
					player.buffTime[num3] = tagCompound.GetInt("time");
				}
			}
		}

		// Token: 0x06001CFC RID: 7420 RVA: 0x00437B78 File Offset: 0x00435D78
		private static void LoadLegacy(Player player, byte[] buffer)
		{
			RijndaelManaged rijndaelManaged = new RijndaelManaged();
			rijndaelManaged.Padding = PaddingMode.None;
			using (MemoryStream memoryStream = new MemoryStream(buffer))
			{
				using (CryptoStream cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateDecryptor(Player.ENCRYPTION_KEY, Player.ENCRYPTION_KEY), CryptoStreamMode.Read))
				{
					using (BinaryReader binaryReader = new BinaryReader(cryptoStream))
					{
						byte b = binaryReader.ReadByte();
						if (b != 0)
						{
							byte[] array = binaryReader.ReadBytes((int)b);
							if (array.Length < 2)
							{
								Array.Resize<byte>(ref array, 2);
							}
							PlayerIO.LoadLegacyModPlayer(player, array, binaryReader);
						}
					}
				}
			}
		}

		// Token: 0x06001CFD RID: 7421 RVA: 0x00437C30 File Offset: 0x00435E30
		private static void LoadLegacyModPlayer(Player player, byte[] flags, BinaryReader reader)
		{
			if ((flags[0] & 1) == 1)
			{
				ItemIO.LoadLegacyInventory(player.armor, reader, false, false);
			}
			if ((flags[0] & 2) == 2)
			{
				ItemIO.LoadLegacyInventory(player.dye, reader, false, false);
			}
			if ((flags[0] & 4) == 4)
			{
				ItemIO.LoadLegacyInventory(player.inventory, reader, true, true);
			}
			if ((flags[0] & 8) == 8)
			{
				ItemIO.LoadLegacyInventory(player.miscEquips, reader, false, false);
			}
			if ((flags[0] & 16) == 16)
			{
				ItemIO.LoadLegacyInventory(player.miscDyes, reader, false, false);
			}
			if ((flags[0] & 32) == 32)
			{
				ItemIO.LoadLegacyInventory(player.bank.item, reader, true, false);
			}
			if ((flags[0] & 64) == 64)
			{
				ItemIO.LoadLegacyInventory(player.bank2.item, reader, true, false);
			}
			if ((flags[0] & 128) == 128)
			{
				PlayerIO.LoadLegacyModData(player, reader);
			}
			if ((flags[1] & 1) == 1)
			{
				PlayerIO.LoadLegacyModBuffs(player, reader);
			}
		}

		// Token: 0x06001CFE RID: 7422 RVA: 0x00437D10 File Offset: 0x00435F10
		private static void LoadLegacyModData(Player player, BinaryReader reader)
		{
			int num = (int)reader.ReadUInt16();
			int i = 0;
			while (i < num)
			{
				string text = reader.ReadString();
				string text2 = reader.ReadString();
				byte[] array = reader.ReadBytes((int)reader.ReadUInt16());
				Mod mod = ModLoader.GetMod(text);
				ModPlayer modPlayer = (mod == null) ? null : player.GetModPlayer(mod, text2);
				if (modPlayer != null)
				{
					using (MemoryStream memoryStream = new MemoryStream(array))
					{
						using (BinaryReader binaryReader = new BinaryReader(memoryStream))
						{
							try
							{
								modPlayer.LoadLegacy(binaryReader);
								goto IL_E2;
							}
							catch (Exception inner)
							{
								throw new CustomModDataException(mod, "Error in reading custom player data for " + mod.Name, inner);
							}
						}
					}
					goto IL_9A;
				}
				goto IL_9A;
				IL_E2:
				i++;
				continue;
				IL_9A:
				TagCompound tagCompound = new TagCompound();
				tagCompound["mod"] = text;
				tagCompound["name"] = text2;
				tagCompound["legacyData"] = array;
				TagCompound item = tagCompound;
				player.GetModPlayer<MysteryPlayer>(ModLoader.GetMod("ModLoader")).data.Add(item);
				goto IL_E2;
			}
		}

		// Token: 0x06001CFF RID: 7423 RVA: 0x00437E34 File Offset: 0x00436034
		private static void LoadLegacyModBuffs(Player player, BinaryReader reader)
		{
			int num = (int)reader.ReadByte();
			int num2 = 0;
			for (int i = 0; i < num; i++)
			{
				int num3 = (int)reader.ReadByte() - num2;
				string name = reader.ReadString();
				string name2 = reader.ReadString();
				int num4 = reader.ReadInt32();
				Mod mod = ModLoader.GetMod(name);
				int num5 = (mod == null) ? 0 : mod.BuffType(name2);
				if (num5 > 0)
				{
					for (int j = 21; j > num3; j--)
					{
						player.buffType[j] = player.buffType[j - 1];
						player.buffTime[j] = player.buffTime[j - 1];
					}
					player.buffType[num3] = num5;
					player.buffTime[num3] = num4;
				}
				else
				{
					num2++;
				}
			}
			for (int k = 1; k < 22; k++)
			{
				if (player.buffType[k] > 0)
				{
					int num6 = k - 1;
					while (player.buffType[num6] == 0)
					{
						player.buffType[num6] = player.buffType[num6 + 1];
						player.buffTime[num6] = player.buffTime[num6 + 1];
						player.buffType[num6 + 1] = 0;
						player.buffTime[num6 + 1] = 0;
						num6--;
					}
				}
			}
		}

		// Token: 0x06001D00 RID: 7424 RVA: 0x000148B5 File Offset: 0x00012AB5
		internal static void LoadUsedMods(Player player, IList<string> usedMods)
		{
			player.usedMods = usedMods;
		}

		// Token: 0x06001D01 RID: 7425 RVA: 0x000148BE File Offset: 0x00012ABE
		internal static List<string> SaveUsedMods(Player player)
		{
			return ModLoader.GetLoadedMods().Except(new string[]
			{
				"ModLoader"
			}).ToList<string>();
		}

		// Token: 0x06001D02 RID: 7426 RVA: 0x000148DD File Offset: 0x00012ADD
		internal static void MoveToCloud(string localPath, string cloudPath)
		{
			localPath = Path.ChangeExtension(localPath, ".tplr");
			cloudPath = Path.ChangeExtension(cloudPath, ".tplr");
			if (File.Exists(localPath))
			{
				FileUtilities.MoveToCloud(localPath, cloudPath);
			}
		}

		// Token: 0x06001D03 RID: 7427 RVA: 0x00014909 File Offset: 0x00012B09
		internal static void MoveToLocal(string cloudPath, string localPath)
		{
			cloudPath = Path.ChangeExtension(cloudPath, ".tplr");
			localPath = Path.ChangeExtension(localPath, ".tplr");
			if (FileUtilities.Exists(cloudPath, true))
			{
				FileUtilities.MoveToLocal(cloudPath, localPath);
			}
		}

		// Token: 0x06001D04 RID: 7428 RVA: 0x00014936 File Offset: 0x00012B36
		internal static void LoadBackup(string path, bool cloudSave)
		{
			path = Path.ChangeExtension(path, ".tplr");
			if (FileUtilities.Exists(path + ".bak", cloudSave))
			{
				FileUtilities.Move(path + ".bak", path, cloudSave, true);
			}
		}

		// Token: 0x06001D05 RID: 7429 RVA: 0x00437F68 File Offset: 0x00436168
		internal static void ErasePlayer(string path, bool cloudSave)
		{
			path = Path.ChangeExtension(path, ".tplr");
			try
			{
				FileUtilities.Delete(path, cloudSave);
				FileUtilities.Delete(path + ".bak", cloudSave);
			}
			catch
			{
			}
		}
	}
}
